前一天已經算出目標中心 target_x 和畫面中心 center_x 之間的偏差,也得到 error_x。現在程式已經可以知道目標是在畫面的左邊、右邊,還是接近中央。如果想讓 TurtleBot3 自動對準目標,只有知道方向還不夠。接下來還需要把畫面中的誤差,轉換成機器人可以使用的旋轉速度。
接下來的問題就是:
既然知道目標偏左或偏右,那機器人到底要轉多快?
最簡單的控制方式,是讓目標在左邊時往左轉,在右邊時往右轉。不過,如果只設定固定速度,不管目標偏了 20 像素,還是已經偏了 200 像素,機器人都會用一樣的速度轉動。
這樣雖然可以讓機器人動起來,但實際追蹤時可能不太自然。目標離中心很遠時,轉速可能不夠快;目標已經靠近中心時,又可能因為轉得太快而直接超過目標。
所以這裡先使用一個簡單的 P 控制(Proportional Control,比例控制),讓旋轉速度可以跟著誤差大小改變。

P 控制的概念可以先理解成:
誤差越大 → 轉得越快
誤差越小 → 轉得越慢
前一天算出的誤差是:
error_x = target_x - center_x
接著把 error_x 乘上一個比例係數 Kp,就可以得到旋轉速度:
angular_z = -Kp * error_x
其中,Kp 可以理解成機器人對誤差有多敏感。同樣的誤差乘上不同的 Kp,最後得到的旋轉速度也會不一樣。
| Kp 的設定 | 機器人的反應 |
|---|---|
| 比較大 | 轉向反應較快,但也比較容易轉過頭 |
| 比較小 | 轉向比較平順,但可能跟不上移動中的目標 |
所以 P 控制做的事情,其實就是把「畫面中偏了多少」轉換成「機器人要轉多快」。
在前一天的計算中,我使用的是:
error_x = target_x - center_x
因此,目標在畫面右側時,error_x 會是正數;在左側時,error_x 會是負數。
但是在 ROS 2 的 Twist 訊息中,angular.z 為正值時,機器人會往左旋轉;為負值時,則會往右旋轉。影像誤差的正負方向,剛好和機器人的旋轉方向相反,所以公式前面需要加上負號。
| 目標位置 | error_x | angular_z | TurtleBot3 的動作 |
|---|---|---|---|
| 畫面左側 | 負數 | 正數 | 往左轉 |
| 畫面中央 | 接近 0 | 接近 0 | 幾乎不轉 |
| 畫面右側 | 正數 | 負數 | 往右轉 |
這個負號不是固定規定,而是和前面計算誤差的順序有關。如果把誤差改成 center_x - target_x,正負方向也會跟著改變。
/cmd_vel 控制 TurtleBot3知道旋轉速度之後,下一步就是把它真的送給 TurtleBot3。
ROS2 中可以使用 geometry_msgs/msg/Twist 來表示機器人的移動速度。今天先讓機器人只做原地轉向,所以前進速度設為 0,再把 P 控制算出的結果放進 angular.z:
twist.linear.x = 0.0
twist.angular.z = angular_z
linear.x 代表前後移動的速度,目前設成 0.0,表示機器人暫時不往前走。angular.z 則代表左右旋轉的速度,這裡會隨著 error_x 的大小與方向改變。
最後再把這個 Twist 訊息發布到 /cmd_vel,TurtleBot3 就能根據相機看到的目標位置開始轉向。
整個流程就會變成:
相機影像
↓
找到紅色目標
↓
計算 target_x
↓
算出 error_x
↓
P 控制
↓
得到 angular.z
↓
發布到 /cmd_vel
↓
TurtleBot3 轉向
假設目標只稍微偏離畫面中心一點點,如果機器人還是用很快的速度轉過去,就有可能直接轉過頭。轉過頭之後,目標又會跑到畫面的另一邊,機器人接著又往反方向轉。
P 控制的好處是,它會根據誤差大小調整轉速。當目標離中心很遠時,可以轉得比較快;當目標逐漸接近畫面中心時,轉速也會跟著降低。因此它比單純使用固定速度轉向,更適合目前這種需要持續調整方向的視覺追蹤。
P 控制也不是加上去之後就一定會變得很穩定。如果 Kp 設太大,機器人可能反應過度;如果設太小,又可能跟不上移動中的目標。這也是後面需要慢慢調整的部分。
對這個專題來說,穩定性會直接影響最後能不能成為一個好用的追蹤系統。尤其我希望之後可以往移動攝影或跟拍的方向發展,如果機器人本身一直抖動,最後拍到的畫面也會跟著晃動。
所以我先把穩定性分成幾個部分來看
第一個是目標辨識本身穩不穩。
例如紅色目標有時候偵測得到,有時候突然消失,或是畫面中其他紅色物體被誤判成目標。
如果輸入的目標位置一直跳動,那後面的控制再怎麼調整,也很難穩定。
這一層主要會和 HSV 範圍、Mask、輪廓篩選與面積門檻有關。
即使每一幀都有找到目標,target_x 也不一定完全固定。
影像雜訊、輪廓形狀變化,都可能讓 Bounding Box 的位置稍微改變。
例如:
target_x = 319
target_x = 323
target_x = 318
target_x = 325
實際上目標可能根本沒有明顯移動,但程式看到的位置仍然會有小幅變化。
如果這些微小誤差全部拿去控制機器人,機器人就可能一直做很小的左右調整。
這是目前 P 控制最直接影響的部分。像是 Kp 太大、旋轉速度沒有上限,或是目標已經接近中央時仍然持續修正,都可能讓機器人反覆左右晃動。
所以後續還可以加入 Dead Zone、最大旋轉速度限制或目標位置平滑,減少不必要的動作。
目前先讓 TurtleBot3 原地旋轉。未來如果開始讓它一邊轉向、一邊往前追蹤,前進速度和旋轉速度就需要互相配合。
如果方向還沒對準就開始往前走,或是機器人突然加速、急轉,即使目標一直留在畫面中,拍出來的影像也可能很晃。
所以未來的目標不只是「追得到」,還需要思考:
機器人追蹤穩定
↓
相機移動穩定
↓
拍到的畫面才會比較穩定
也就是說,後面的控制除了要讓目標留在畫面中,也要讓機器人的動作更平順。
error_x。angular_z = -Kp * error_x。Twist 訊息發布到 /cmd_vel,讓機器人朝目標旋轉。這一步完成後,TurtleBot3 已經不只是「看得到目標」,而是第一次開始根據相機畫面中的資訊做出動作。
不過,實際動起來後,也出現左右來回修正、轉向過快,以及目標接近中央時仍然持續調整的問題。接下來的重點,就會從「讓它動起來」,慢慢變成「讓它動得更穩」。
下一篇會開始改善追蹤的穩定性,先從 Dead Zone 與最大旋轉速度限制開始。當目標已經接近畫面中央時,讓機器人暫時不要一直修正;誤差很大時,也不讓旋轉速度無限制增加。
除了讓機器人比較不容易左右晃動,也會繼續觀察 Kp 要怎麼調整,才能在反應速度與穩定性之間找到適合的平衡。